{% extends 'layouts/default.html' %}
{% set title = '客户详情' %}
{% set menuActive = 'customers' %}
{% block container %}
<div class="d-flex align-items-baseline">
    <div class="h4 mb-4">客户 - 详情</div>
</div>
<div class="row">
    <div class="col-md-4">
        <div class="card mb-3" aria-hidden="true">
            <div class="card-body">
                <div class="card-title">
                    <div class="d-flex align-items-baseline justify-content-between">
                        <div class="fs-5">{{ data.customer.name }}</div>
                    </div>
                </div>
                <div class="d-flex flex-column">
                    <div class="d-flex">
                        <div class="me-2 text-nowrap">电话:</div>
                        <div>{{ data.customer.phone }}</div>
                    </div>
                    <div class="my-1 d-flex">
                        <div class="me-2 text-nowrap">类型:</div>
                        <div>{{ data.customer.type }}</div>
                    </div>
                    <div class="my-1 d-flex">
                        <div class="me-2 text-nowrap">地区:</div>
                        <div>{{ data.customer.province }} / {{ data.customer.city }}
                            / {{ data.customer.area }}</div>
                    </div>
                    <div class="my-1 d-flex">
                        <div class="me-2 text-nowrap">地址:</div>
                        <div>{{ data.customer.address }}</div>
                    </div>
                    <div class="my-1 d-flex">
                        <div class="me-2 text-nowrap">坐标:</div>
                        <div>{{ data.customer.location }}</div>
                    </div>
                    <div class="my-1 d-flex">
                        <div class="me-2 text-nowrap">阶段:</div>
                        <div class="dropdown">
                            <div id="stage" class="badge dropdown-toggle"
                                style="cursor: pointer; background-color: {{ data.customer.stage.colorHex if data.customer.stage.colorHex else '#212529' }};"
                                data-bs-toggle="dropdown" aria-expanded="false">
                                {{ data.customer.stage.name }}
                            </div>
                            <ul class="dropdown-menu">
                                {% for s in data.stages %}
                                <li>
                                    <div class="dropdown-item d-flex align-items-center" style="cursor: pointer;"
                                        onclick="app.changeStage('{{s.id}}', '{{s.name}}', '{{s.colorHex}}')">
                                        <label class="color-cube me-2 cursor-pointer"
                                            style="background-color:{{s.colorHex}};"></label>
                                        {{s.name}}
                                    </div>
                                </li>
                                {% endfor %}
                            </ul>
                        </div>
                    </div>
                    <div class="my-1 d-flex">
                        <div class="me-2 text-nowrap">标签:</div>
                        <div id="tags" class="tags"></div>
                    </div>
                </div>
            </div>
            <div class="card-footer bg-transparent">
                {% if sessionUser.isAdmin %}
                <button class="btn btn-dark btn-sm me-1" onclick="app.edit('{{ data.customer.id }}')">编辑</button>
                {% endif %}
                <button class="btn btn-dark btn-sm me-1" onclick="app.transfer('{{ data.customer.id }}')">转交
                </button>
                <button class="btn btn-danger btn-sm" onclick="app.retreat('{{ data.customer.id }}')">退回
                </button>
            </div>
        </div>
        <div class="d-flex g-2 flex-wrap">
            {% for photo in data.customer.photos %}
            <div class="m-1 border border-1 p-1" style="max-width: 150px;" onclick="helper.preview('{{ photo.url }}')">
                <img src="{{ photo.url }}" width="100%" />
            </div>
            {% endfor %}
        </div>
    </div>
    <div class="col-md-8">
        <div class="d-flex justify-content-between flex-wrap mb-3">
            <ul class="nav nav-tabs">
                <li class="nav-item">
                    <a id="tabActivity" class="nav-link" href="#" onclick="app.switchTab('activity')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
                            class="bi bi-activity" viewBox="0 0 16 16">
                            <path fill-rule="evenodd"
                                d="M6 2a.5.5 0 0 1 .47.33L10 12.036l1.53-4.208A.5.5 0 0 1 12 7.5h3.5a.5.5 0 0 1 0 1h-3.15l-1.88 5.17a.5.5 0 0 1-.94 0L6 3.964 4.47 8.171A.5.5 0 0 1 4 8.5H.5a.5.5 0 0 1 0-1h3.15l1.88-5.17A.5.5 0 0 1 6 2Z" />
                        </svg>
                        动态
                    </a>
                </li>
                <li class="nav-item">
                    <a id="tabLink" class="nav-link" href="#" onclick="app.switchTab('link')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
                            class="bi bi-link-45deg" viewBox="0 0 16 16">
                            <path
                                d="M4.715 6.542 3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1.002 1.002 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4.018 4.018 0 0 1-.128-1.287z" />
                            <path
                                d="M6.586 4.672A3 3 0 0 0 7.414 9.5l.775-.776a2 2 0 0 1-.896-3.346L9.12 3.55a2 2 0 1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243L6.586 4.672z" />
                        </svg>
                        联系
                    </a>
                </li>
                <li class="nav-item">
                    <a id="tabContract" class="nav-link" href="#" onclick="app.switchTab('contract')">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
                            class="bi bi-folder2" viewBox="0 0 16 16">
                            <path
                                d="M1 3.5A1.5 1.5 0 0 1 2.5 2h2.764c.958 0 1.76.56 2.311 1.184C7.985 3.648 8.48 4 9 4h4.5A1.5 1.5 0 0 1 15 5.5v7a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 1 12.5v-9zM2.5 3a.5.5 0 0 0-.5.5V6h12v-.5a.5.5 0 0 0-.5-.5H9c-.964 0-1.71-.629-2.174-1.154C6.374 3.334 5.82 3 5.264 3H2.5zM14 7H2v5.5a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5V7z" />
                        </svg>
                        合同
                    </a>
                </li>
            </ul>
            <div class="mt-2 tab-toolbar"></div>
        </div>
        <div id="spinner" class="text-center" style="display: none;">
            <div class="spinner-border" role="status"></div>
        </div>
        <div id="tabContent" class="p-1 activity-container"></div>
    </div>
</div>
{% endblock container %}
{% block script %}
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/litepicker/dist/litepicker.js"></script>
<script src="/public/js/customers.js"></script>
<script src="/public/js/activities.js"></script>
<script>
    const app = {
        data: {
            link: {
                list: [],
                skip: 0,
                limit: 15,
                count: 0,
            },
            contractProductList: [],
            activity: {
                list: [],
                skip: 0,
                limit: 15,
                count: 0,
            },
            contractList: [],
        },
        tags: {
            tagsDialog: {
                title: '标签',
                id: 'tagsDialog',
                data: {},
                open({ customerId, onDone, onFail, onAlways }) {
                    this.data.customerId = customerId;
                    this.onDone = onDone;
                    this.onFail = onFail;
                    this.onAlways = onAlways;
                    this.render();
                },
                setTag(tagName) {
                    document.querySelector(`#${this.id} input[name="tag"]`).value = tagName;
                },
                render() {
                    const modal = this;
                    const modalEL = document.createElement('div');
                    modalEL.id = modal.id;
                    modalEL.className = 'modal fade';
                    modalEL.setAttribute('aria-hidden', 'true');
                    modalEL.setAttribute('tabindex', '-1');
                    modalEL.setAttribute('data-bs-backdrop', 'static');
                    modalEL.addEventListener('hidden.bs.modal', () => {
                        modal.data = {};
                        document.body.removeChild(modalEL);
                    });
                    modalEL.addEventListener('show.bs.modal', () => {
                        // load some tags (hot)
                        $.getJSON('/tags?customerId={{data.customer.id}}').done(function (result) {
                            const { data } = result;
                            const parentNode = $(`#${modal.id} .tags`);
                            for (const u of data) {
                                parentNode.append(`<div class="tag" onclick="app.tags.tagsDialog.setTag('${u.name}')">${u.name}</div>`);
                            }
                        });
                    });
                    document.body.appendChild(modalEL);
                    modalEL.innerHTML = `
                <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">${modal.title}</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                        </div>
                        <div class="modal-body">
                            <div class="d-flex flex-column">
                                <div class="mb-3 row">
                                    <label class="col-sm-2 col-form-label">标签</label>
                                    <div class="col-sm-10">
                                        <div class="pb-2 pb-lg-0">
                                            <input name="tag" class="form-control" placeholder="添加或者选择一个标签"></input>
                                        </div>
                                    </div>
                                </div>
                                <div class="mb-3 row">
                                    <label class="col-sm-2 col-form-label">颜色</label>
                                    <div class="col-sm-10 d-flex align-items-center">
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#212529" checked>
                                                <span class="color-check-color" style="background-color:#212529;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#6C757D">
                                                <span class="color-check-color" style="background-color:#6C757D;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#206bc4">
                                                <span class="color-check-color" style="background-color:#206bc4;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#4299e1">
                                                <span class="color-check-color" style="background-color:#4299e1;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#4263eb">
                                                <span class="color-check-color" style="background-color:#4263eb;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#ae3ec9">
                                                <span class="color-check-color" style="background-color:#ae3ec9;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#d6336c">
                                                <span class="color-check-color" style="background-color:#d6336c;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#d63939">
                                                <span class="color-check-color" style="background-color:#d63939;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#f76707">
                                                <span class="color-check-color" style="background-color:#f76707;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#f59f00">
                                                <span class="color-check-color" style="background-color:#f59f00;"></span>
                                            </div>
                                        </label>
                                        <label class="color-input">
                                            <div class="col-auto">
                                                <input class="color-check-input" name="tagColor" type="radio" value="#74b816">
                                                <span class="color-check-color" style="background-color:#74b816;"></span>
                                            </div>
                                        </label>
                                    </div>
                                </div>
                                <div class="mb-3 d-flex flex-wrap align-items-center tags"></div>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                            <button type="button" class="btn btn-dark">保存</button>
                        </div>
                    </div>
                </div>
            `;
                    document.querySelector(`#${modal.id} .btn-dark`).addEventListener('click', () => {
                        const name = document.querySelector(`#${modal.id} input[name="tag"]`).value;
                        const color = document.querySelector(`#${modal.id} input[name="tagColor"]:checked`).value;
                        $.ajax({
                            url: `/customers/${modal.data.customerId}/tags`,
                            type: 'post',
                            data: { name, color }
                        }).done(function () {
                            if (modal.onDone) modal.onDone();
                        }).fail(function (result) {
                            if (modal.onFail) modal.onFail(result);
                        }).always(function () {
                            $(`#${modal.id}`).modal('hide');
                            if (modal.onAlways) modal.onAlways();
                        });
                    });
                    $(`#${modal.id}`).modal('show');
                },
            },
            newTag(customerId) {
                app.tags.tagsDialog.open({
                    customerId,
                    onDone: () => { helper.toast('操作成功', 'success'); app.tags.renderTags(); },
                    onFail: (result) => {
                        if (result.status === 400) {
                            helper.toast(result.responseJSON?.message || '未知错误，请刷新重试', 'warning');
                        } else {
                            helper.toast('操作失败，请刷新重试或者联系管理员', 'danger');
                        }
                    }
                });
            },
            deleteTag(tagId) {
                $.ajax({
                    type: 'delete',
                    url: `/customers/{{data.customer.id}}/tags/${tagId}`,
                }).done(function () {
                    helper.toast('操作成功', 'success');
                    app.tags.renderTags();
                });
            },
            renderTags() {
                $.getJSON('/customers/{{data.customer.id}}/tags')
                    .done(function (result) {
                        const tags = document.querySelector('#tags');
                        let tagsHTML = '';
                        for (const tag of result.data) {
                            tagsHTML += `
                            <div class="tag tag-secondary" style="background-color:${tag.colorHex || ''};">
                                ${tag.name}
                                <button type="button" class="btn-close btn-close-white btn-close-sm delete" onclick="app.tags.deleteTag(${tag.id})"></button>
                            </div>
                        `;
                        }
                        tagsHTML += `
                        <div class="d-flex aligne-items-center mb-2">
                            <button class="btn btn-outline-secondary btn-mini py-0"
                                onclick="app.tags.newTag('{{data.customer.id}}')">
                                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
                                    class="bi bi-plus" viewBox="0 0 16 16">
                                    <path
                                        d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
                                </svg>
                            </button>
                        </div>
                    `;
                        tags.innerHTML = tagsHTML;
                    });
            },
        },
        activities: {
            loadActivityList(more) {
                if (more) {
                    app.data.activity.skip = app.data.activity.skip + app.data.activity.limit;
                } else {
                    app.data.activity.list = [];
                    app.data.activity.skip = 0;
                }
                $('#spinner').show();
                $.ajax({
                    type: 'get',
                    url: `/customers/{{data.customer.id}}/activities`,
                    data: { skip: app.data.activity.skip, limit: app.data.activity.limit },
                    statusCode: { 401: () => window.location.href = '/login', }
                }).done(function (result) {
                    const { data, limit, skip, count } = result;
                    app.data.activity.list = [...app.data.activity.list, ...data];
                    app.data.activity.count = count;
                    app.activities.renderActivityList();
                }).always(function () {
                    $('#spinner').hide();
                });
            },
            renderActivityList() {
                let html = activities.render({ data: app.data.activity.list, isMy: false }); // !!!this 'activities' comes from activities.js
                html += app.data.activity.list.length < app.data.activity.count ? `
                    <div class="d-flex mt-2">
                        <button class="btn btn-dark" onclick="app.activities.loadActivityList(true)">加载更多</button>
                    </div>
                ` : '';
                document.getElementById('tabContent').innerHTML = html;
            },
        },
        links: {
            typeDefault: `
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chat-right-text-fill" viewBox="0 0 16 16">
                    <path d="M16 2a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h9.586a1 1 0 0 1 .707.293l2.853 2.853a.5.5 0 0 0 .854-.353V2zM3.5 3h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1 0-1zm0 2.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1 0-1zm0 2.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1 0-1z"/>
                    </svg>
                `,
            typeMap: {
                '微信': `
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-wechat" viewBox="0 0 16 16">
                        <path d="M11.176 14.429c-2.665 0-4.826-1.8-4.826-4.018 0-2.22 2.159-4.02 4.824-4.02S16 8.191 16 10.411c0 1.21-.65 2.301-1.666 3.036a.324.324 0 0 0-.12.366l.218.81a.616.616 0 0 1 .029.117.166.166 0 0 1-.162.162.177.177 0 0 1-.092-.03l-1.057-.61a.519.519 0 0 0-.256-.074.509.509 0 0 0-.142.021 5.668 5.668 0 0 1-1.576.22ZM9.064 9.542a.647.647 0 1 0 .557-1 .645.645 0 0 0-.646.647.615.615 0 0 0 .09.353Zm3.232.001a.646.646 0 1 0 .546-1 .645.645 0 0 0-.644.644.627.627 0 0 0 .098.356Z" />
                        <path d="M0 6.826c0 1.455.781 2.765 2.001 3.656a.385.385 0 0 1 .143.439l-.161.6-.1.373a.499.499 0 0 0-.032.14.192.192 0 0 0 .193.193c.039 0 .077-.01.111-.029l1.268-.733a.622.622 0 0 1 .308-.088c.058 0 .116.009.171.025a6.83 6.83 0 0 0 1.625.26 4.45 4.45 0 0 1-.177-1.251c0-2.936 2.785-5.02 5.824-5.02.05 0 .1 0 .15.002C10.587 3.429 8.392 2 5.796 2 2.596 2 0 4.16 0 6.826Zm4.632-1.555a.77.77 0 1 1-1.54 0 .77.77 0 0 1 1.54 0Zm3.875 0a.77.77 0 1 1-1.54 0 .77.77 0 0 1 1.54 0Z" />
                    </svg>
                `,
                '邮件': `
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-fill" viewBox="0 0 16 16">
                        <path d="M.05 3.555A2 2 0 0 1 2 2h12a2 2 0 0 1 1.95 1.555L8 8.414.05 3.555ZM0 4.697v7.104l5.803-3.558L0 4.697ZM6.761 8.83l-6.57 4.027A2 2 0 0 0 2 14h12a2 2 0 0 0 1.808-1.144l-6.57-4.027L8 9.586l-1.239-.757Zm3.436-.586L16 11.801V4.697l-5.803 3.546Z"/>
                    </svg>
                `,
                '电话': `
                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" class="bi bi-telephone-fill" viewBox="0 0 16 16">
                        <path fill-rule="evenodd" d="M1.885.511a1.745 1.745 0 0 1 2.61.163L6.29 2.98c.329.423.445.974.315 1.494l-.547 2.19a.678.678 0 0 0 .178.643l2.457 2.457a.678.678 0 0 0 .644.178l2.189-.547a1.745 1.745 0 0 1 1.494.315l2.306 1.794c.829.645.905 1.87.163 2.611l-1.034 1.034c-.74.74-1.846 1.065-2.877.702a18.634 18.634 0 0 1-7.01-4.42 18.634 18.634 0 0 1-4.42-7.009c-.362-1.03-.037-2.137.703-2.877L1.885.511z" />
                    </svg>
                `,
                'QQ': `
                    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
                        <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
                        <path d="M14 7h.01"></path>
                        <path d="M10 7h.01"></path>
                        <path d="M6 11c4 4 8 4 12 0"></path>
                        <path d="M9 13.5v2.5"></path>
                        <path d="M10.5 10c.667 1.333 2.333 1.333 3 0h-3z"></path>
                        <path d="M16 21c1.5 0 3.065 -1 1 -3c4.442 2 1.987 -4.5 1 -7c0 -4 -1.558 -8 -6 -8s-6 4 -6 8c-.987 2.5 -3.442 9 1 7c-2.065 2 -.5 3 1 3h8z"></path>
                    </svg>
                `,
            },
            loadLinkList(more) {
                if (more) {
                    app.data.link.skip = app.data.link.skip + app.data.link.limit;
                } else {
                    app.data.link.list = [];
                    app.data.link.skip = 0;
                }
                $('#spinner').show();
                $.ajax({
                    type: 'get',
                    url: `/customers/{{data.customer.id}}/links`,
                    data: { skip: app.data.link.skip, limit: app.data.link.limit },
                    statusCode: { 401: () => window.location.href = '/login', }
                }).done(function (result) {
                    const { data, skip, limit, count } = result;
                    app.data.link.list = [...app.data.link.list, ...data];
                    app.data.link.count = count;
                    app.links.renderLinkList();
                }).always(function () {
                    $('#spinner').hide();
                });
            },
            renderLinkList() {
                let html = '';
                for (let i = 0; i < app.data.link.list.length; i++) {
                    const item = app.data.link.list[i];
                    html += `
                        <div class="d-flex">
                            <div class="d-flex flex-column me-2">
                                <div class="text-bg-dark rounded-circle d-flex align-items-center justify-content-center activity-icon-sm text-center">
                                    ${this.typeMap[item.type.name] || this.typeDefault}
                                </div>
                                <div class="bg-secondary align-self-center my-1 opacity-25 flex-grow-1" style="width:2px;"></div>
                            </div>
                            <div class="d-flex flex-column flex-grow-1 mb-4">
                                <div class="p-2 border border-dark border-opacity-25 shadow-sm rounded mb-2">
                                    <div class="d-flex flex-column">
                                        <div class="d-flex justify-content-between mb-2">
                                            <div class="d-flex flex-column">
                                                <div class="fs-5">${item.subject}</div>
                                                <div class="d-flex align-items-baseline">
                                                    <div class="fs-sm text-muted">${item.user.name}</div>
                                                    <div class="mx-1">·</div>
                                                    <div class="fs-sm text-muted">${item.type.name}</div>
                                                    <div class="mx-1">·</div>
                                                    <div class="fs-sm text-muted">${dayjs(item.updatedAt).format("YYYY-MM-DD HH:mm:ss")}</div>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="paragraph mb-1">
                                            ${item.content}
                                        </div>
                                    </div>
                                </div>
                                <div class="mb-1 ms-1">
                                    <button class="btn btn-sm btn-light" onclick="app.links.openLinkForm(${i})">编辑</button>
                                    <button class="btn btn-sm btn-light" onclick="app.links.deleteLink(${i})">删除</button>
                                </div>
                            </div>
                        </div>
                    `;
                }
                html += app.data.link.list.length < app.data.link.count ? `
                    <div class="d-flex mt-2">
                        <button class="btn btn-dark" onclick="app.links.loadLinkList(true)">加载更多</button>
                    </div>
                ` : '';
                document.getElementById('tabContent').innerHTML = html;
            },
            deleteLink(itemIndex) {
                const item = itemIndex > -1 ? app.data.link.list[itemIndex] : undefined;
                if (item) {
                    helper.confirm('确定删除这个联系吗？', function () {
                        $.ajax({
                            type: 'delete',
                            url: `/customers/{{data.customer.id}}/links/${item.id}`,
                            statusCode: { 401: () => window.location.href = '/login', }
                        }).done(function () {
                            app.data.link.list = app.data.link.list.filter((_, i) => i !== itemIndex);
                            app.data.link.count -= 1; // we delete one!
                            app.links.renderLinkList();
                            helper.toast('操作成功', 'success');
                        });
                    });
                }
            },
            openLinkForm(itemIndex) {
                $.ajax({
                    type: 'get',
                    url: '/links/types',
                    statusCode: { 401: () => window.location.href = '/login', }
                }).done(function (result) {
                    const item = itemIndex > -1 ? app.data.link.list[itemIndex] : undefined;
                    const { data } = result;
                    let optionsHTML = '';
                    for (let i = 0; i < data.length; i++) {
                        const option = data[i];
                        optionsHTML += `<option ${option.id === item?.type.id ? 'selected' : ''} value="${option.id}">${option.name}</option>`;
                    }
                    // show modal
                    const editorEl = document.createElement('div');
                    editorEl.id = 'editor';
                    editorEl.className = 'modal fade';
                    editorEl.setAttribute('aria-hidden', 'true');
                    editorEl.setAttribute('tabindex', '-1');
                    editorEl.setAttribute('data-bs-backdrop', 'static');
                    editorEl.addEventListener('hidden.bs.modal', () => document.body.removeChild(editorEl));
                    document.body.appendChild(editorEl);
                    editorEl.innerHTML = `
                    <div class="modal-dialog modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">${item ? '编辑联系' : '新建联系'}</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                            </div>
                            <form id="editorForm">
                            <div class="modal-body">
                                <div class="mb-3 row">
                                    <label for="linkType" class="col-sm-2 form-label">方式</label>
                                    <div class="col-sm-10">
                                        <select class="form-select" name="typeId" id="linkType" name="typeId">
                                            ${optionsHTML}
                                        </select>
                                    </div>
                                </div>
                                <div class="mb-3 row">
                                    <label class="col-sm-2 form-label">主题</label>
                                    <div class="col-sm-10">
                                        <input type="text" class="form-control" name="subject" value="${item?.subject || ''}">
                                    </div>
                                </div>
                                <div class="row">
                                    <label class="col-sm-2 form-label">内容</label>
                                    <div class="col-sm-10">
                                        <textarea class="form-control" name="content" rows="3">${item?.content || ''}</textarea>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                                <button type="button" class="btn btn-dark">保存</button>
                            </div>
                            </form>
                        </div>
                    </div>
                `;
                    document.querySelector('#editor .btn-dark').addEventListener('click', () => {
                        const data = {};
                        new FormData(document.getElementById('editorForm')).forEach((v, k) => {
                            data[k] = v;
                            if (item) item[k] = v; // update local item
                        });
                        if (item?.id) data.id = item.id;

                        $.ajax({
                            url: `/customers/{{data.customer.id}}/links`,
                            type: 'post',
                            data,
                            statusCode: { 401: () => window.location.href = '/login', }
                        }).done(function () {
                            helper.toast('操作成功', 'success');
                        }).always(function (result) {
                            $('#editor').modal('hide');
                            if (!item) app.data.link.list = [result.data, ...app.data.link.list]; // push new item to head
                            app.links.renderLinkList();
                        });
                    });
                    $('#editor').modal('show');
                });
            },
        },
        retreat(customerId) {
            helper.confirm('确定退回吗？', function () {
                $.ajax({
                    type: 'post',
                    url: `/customers/${customerId}/retreat`,
                }).done(function (result) {
                    window.location.href = '/customers/my';
                });
            });
        },
        transfer(customerId) {
            transferDialog.open({
                customerId,
                currentUserId: '{{sessionUser.id}}',
                onDone: () => window.location.href = '/customers/my',
                onFail: () => helper.toast('操作失败，请联系系统管理员。', 'danger'),
            });
        },
        edit(customerId) {
            $.ajax({
                url: `/customers/${customerId}`,
                contentType: 'application/json',
            }).done(function (result) {
                $.getJSON('/public/regions').done(function (regions) {
                    editor.open({
                        title: '编辑',
                        regions,
                        data: result,
                        onDone: () => window.location.reload(),
                        onFail: () => helper.toast('操作失败，请联系系统管理员。', 'danger'),
                    });
                }).fail(() => helper.toast('无法从服务器获取数据，请等会再试，或者联系管理员。', 'danger'));
            }).fail(function () {
                helper.toast('无法从服务器获取数据，请等会再试，或者联系管理员。', 'danger');
            });
        },
        changeStage(stageId, stageName, stageColorHex) {
            $.ajax({
                type: 'put',
                url: `/customers/{{data.customer.id}}/stage`,
                data: { stageId },
            }).done(function (result) {
                const stage = document.getElementById('stage');
                stage.textContent = stageName;
                stage.style = `background-color: ${stageColorHex || '#212529'};`;
                if (app.isTabActive('#tabActivity')) app.loadActivityList();
                helper.toast('操作成功', 'success');
            });
        },
        // tab
        isTabActive(tabId) {
            return document.querySelector(tabId).classList.contains('active');
        },
        switchTab(name) {
            document.querySelector('.tab-toolbar').innerHTML = ''; // clear toolbar
            document.getElementById('tabContent').innerHTML = ''; // clear tab content
            document.querySelectorAll('.nav-item a').forEach(el => el.classList.remove('active'));
            switch (name) {
                case 'activity': {
                    document.querySelector('#tabActivity').classList.add('active');
                    app.activities.loadActivityList();
                    break;
                }
                case 'contract': {
                    document.querySelector('#tabContract').classList.add('active');
                    document.querySelector('.tab-toolbar').innerHTML = `<button class="btn btn-dark btn-sm" onclick="app.openContractForm()">新增</button>`;
                    app.loadContractList();
                    break;
                }
                default: { // default is link
                    document.querySelector('#tabLink').classList.add('active');
                    document.querySelector('.tab-toolbar').innerHTML = `<button class="btn btn-dark btn-sm" onclick="app.links.openLinkForm()">新增</button>`;
                    app.links.loadLinkList();
                    break;
                }
            }
        },
        // contract
        loadContractList() {
            $('#spinner').show();
            $.ajax({
                type: 'get',
                url: `/customers/{{data.customer.id}}/contracts`,
                statusCode: { 401: () => window.location.href = '/login', }
            }).done(function (result) {
                const { data } = result;
                app.data.contractList = data;
                app.renderContractList();
            }).always(function () {
                $('#spinner').hide();
            });
        },
        renderContractList() {
            let rows = '';
            for (let i = 0; i < app.data.contractList.length; i++) {
                const item = app.data.contractList[i];
                let actions = ``;
                if (!item.isAbandoned && !item.isCompleted) {
                    actions = `
                        <button class="btn btn-sm btn-dark ms-1" onclick="app.openContractForm(${i})">编辑</button>
                        <button class="btn btn-sm btn-dark ms-1" onclick="app.openReceivableForm(${i})">回款</button>
                        <button class="btn btn-sm btn-dark ms-1" onclick="app.completeContract(${item.id})">完成</button>
                        <button class="btn btn-sm btn-danger ms-1" onclick="app.abandonContract(${item.id})">作废</button>
                    `;
                } else {
                    actions = `<button class="btn btn-sm btn-dark ms-1" onclick="app.openContractForm(${i})">查看</button>`;
                }
                const receivableAmount = item.receivables.reduce((acc, cur) => acc + Number(cur.amount) || 0, 0);
                const receivablePercent = receivableAmount * 100 / (Number(item.amount) || 0.01);
                rows += `
                    <tr id="contract-row-${item.id}">
                        <td>
                            <div class="">${item.number}</div>
                            <div class="">${item.name}</div>
                            ${item.isAbandoned ? '<div class="tag tag-secondary bg-danger mt-1">已作废</div>' : ''}
                            ${item.isCompleted ? '<div class="tag tag-secondary bg-dark mt-1">已完成</div>' : ''}
                        </td>
                        <td>
                            <div class="d-flex flex-column">
                                <div class="d-flex align-items-center" style="margin-bottom: 2px;">
                                    <div class="d-flex align-items-center text-muted">
                                        ¥${receivableAmount}
                                    </div>
                                    <div class="mx-1">/</div>
                                    <div class="d-flex align-items-center">
                                        ¥${item.amount}
                                    </div>
                                </div>
                                <div class="progress cursor-pointer" onclick="app.openReceivableListModal(${i})">
                                    <div class="progress-bar bg-success" role="progressbar" style="width: ${receivablePercent}%" aria-valuenow="${receivablePercent}" aria-valuemin="0" aria-valuemax="100"></div>
                                </div>
                            </div>
                        </td>
                        <td><div class="">${item.remark}</div></td>
                        <td>
                            <div class="">${dayjs(item.createdAt).format("YYYY-MM-DD")}</div>
                            <div class="">${dayjs(item.createdAt).format("HH:mm:ss")}</div>
                        </td>
                        <td>
                            <div class="">${dayjs(item.updatedAt).format("YYYY-MM-DD")}</div>
                            <div class="">${dayjs(item.updatedAt).format("HH:mm:ss")}</div>
                        </td>
                        <td>
                            <div class="d-flex align-items-center">${actions}</div>
                        </td>
                    </tr>
                `;
            }
            const html = `
            <div class="table-responsive">
            <table class="table table-bordered table-group-divider table-light">
                <thead>
                    <tr>
                        <th scope="col">合同</th>
                        <th scope="col">金额</th>
                        <th scope="col">备注</th>
                        <th scope="col">创建</th>
                        <th scope="col">更新</th>
                        <th scope="col" style="width: 220px;min-width: 220px;">操作</th>
                    </tr>
                </thead>
                <tbody class="fs-sm">
                    ${rows}
                </tbody>
            </table>
            </div>
            `;
            document.getElementById('tabContent').innerHTML = html;
        },
        abandonContract(itemId) {
            if (itemId) {
                helper.confirm('确定作废这个合同吗？作废后该合同将不能再改动，且金额将不再计入业务统计。', function () {
                    $.ajax({
                        type: 'post',
                        url: `/customers/{{data.customer.id}}/contracts/${itemId}/abandon`,
                        statusCode: { 401: () => window.location.href = '/login', }
                    }).done(function () {
                        app.loadContractList();
                        helper.toast('操作成功', 'success');
                    });
                });
            }
        },
        completeContract(itemId) {
            if (itemId) {
                helper.confirm('确定完成这个合同吗？完成后该合同将不能再改动', function () {
                    $.ajax({
                        type: 'post',
                        url: `/customers/{{data.customer.id}}/contracts/${itemId}/complete`,
                        statusCode: { 401: () => window.location.href = '/login', }
                    }).done(function () {
                        app.loadContractList();
                        helper.toast('操作成功', 'success');
                    });
                });
            }
        },
        openContractForm(itemIndex) {
            const item = itemIndex > -1 ? app.data.contractList[itemIndex] : undefined;
            const disabled = item && (item.isAbandoned || item.isCompleted);
            // show modal
            const editorId = 'contractEditor';
            const editorEl = document.createElement('div');
            editorEl.id = editorId;
            editorEl.className = 'modal fade';
            editorEl.setAttribute('aria-hidden', 'true');
            editorEl.setAttribute('tabindex', '-1');
            editorEl.setAttribute('data-bs-backdrop', 'static');
            editorEl.addEventListener('hidden.bs.modal', () => document.body.removeChild(editorEl));
            document.body.appendChild(editorEl);
            editorEl.innerHTML = `
                    <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">${disabled ? '编辑' : '查看'}合同</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                            </div>
                            <form id="editorForm" class="modal-body">
                                <div class="mb-3 row">
                                    <label class="col-sm-2 form-label">编号</label>
                                    <div class="col-sm-10">
                                        <input type="text" class="form-control" name="number" value="${item?.number || ''}" placeHolder="不填则系统自动生成" ${disabled ? 'disabled' : ''}>
                                    </div>
                                </div>
                                <div class="mb-3 row">
                                    <label class="col-sm-2 form-label">名称</label>
                                    <div class="col-sm-10">
                                        <input type="text" class="form-control" name="name" value="${item?.name || ''}" ${disabled ? 'disabled' : ''}>
                                    </div>
                                </div>
                                <div class="mb-3 row">
                                    <label class="col-sm-2 form-label">金额</label>
                                    <div class="col-sm-10">
                                        <input type="number" class="form-control" name="amount" min="0" value="${item?.amount || ''}"${disabled ? 'disabled' : ''}>
                                    </div>
                                </div>
                                <div class="mb-3 row">
                                    <label class="col-sm-2 form-label">备注</label>
                                    <div class="col-sm-10">
                                        <textarea class="form-control" name="remark" rows="3" ${disabled ? 'disabled' : ''}>${item?.remark || ''}</textarea>
                                    </div>
                                </div>
                                <div class="my-3 d-flex flex-column">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <label class="form-label">产品</label>
                                        ${disabled ? '' : `
                                            <a class="form-label fs-sm" href="#" onclick="app.openProductListModal()">增加产品</a>
                                        `}
                                    </div>
                                    <div class="table-responsive"></div>
                                </div>
                            </form>
                            <div class="modal-footer">
                                ${disabled ? `
                                <button type="button" class="btn btn-dark" data-bs-dismiss="modal">关闭</button>
                                    `: `
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                                <button type="button" class="btn btn-dark">保存</button>
                                    `}
                            </div>
                        </div>
                    </div>
                `;
            if (!disabled) {
                document.querySelector(`#${editorId} .btn-dark`).addEventListener('click', () => {
                    const data = {};
                    new FormData(document.querySelector(`#${editorId} #editorForm`)).forEach((v, k) => data[k] = v);
                    if (item?.id) data.id = item.id;
                    data.contractProductList = app.data.contractProductList;

                    $.ajax({
                        url: `/customers/{{data.customer.id}}/contracts`,
                        type: 'post',
                        contentType: 'application/json',
                        headers: { accept: 'application/json' },
                        data: JSON.stringify(data),
                        statusCode: { 401: () => window.location.href = '/login', }
                    }).done(function () {
                        helper.toast('操作成功', 'success');
                    }).always(function () {
                        $(`#${editorId}`).modal('hide');
                        app.loadContractList();
                    });
                });
            }
            $(`#${editorId}`).modal('show');
            app.loadContractProductList(item);
        },
        // contact receivable
        openReceivableForm(itemIndex) {
            $.ajax({
                type: 'get',
                url: '/payment-methods',
                statusCode: { 401: () => window.location.href = '/login', }
            }).done(function (result) {
                const item = itemIndex > -1 ? app.data.contractList[itemIndex] : undefined;
                // read paymentMethods from server
                const { data } = result;
                let optionsHTML = '';
                for (let i = 0; i < data.length; i++) {
                    const option = data[i];
                    optionsHTML += `<option value="${option.id}">${option.name}</option>`;
                }
                // show modal
                const editorEl = document.createElement('div');
                editorEl.id = 'editor';
                editorEl.className = 'modal fade';
                editorEl.setAttribute('aria-hidden', 'true');
                editorEl.setAttribute('tabindex', '-1');
                editorEl.setAttribute('data-bs-backdrop', 'static');
                editorEl.addEventListener('hidden.bs.modal', () => document.body.removeChild(editorEl));
                document.body.appendChild(editorEl);
                editorEl.innerHTML = `
                    <div class="modal-dialog modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">新增回款</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                            </div>
                            <form id="editorForm">
                                <div class="modal-body">
                                    <div class="mb-3 row">
                                        <label class="col-sm-2 form-label">方式</label>
                                        <div class="col-sm-10">
                                            <select class="form-select" name="paymentMethodId" name="paymentMethodId">
                                                ${optionsHTML}
                                            </select>
                                        </div>
                                    </div>
                                    <div class="mb-3 row">
                                        <label class="col-sm-2 form-label">金额</label>
                                        <div class="col-sm-10">
                                            <input type="number" class="form-control" min="0" name="amount">
                                        </div>
                                    </div>
                                    <div class="mb-3 row">
                                        <label class="col-sm-2 form-label">日期</label>
                                        <div class="col-sm-10">
                                            <input class="form-control" placeholder="选择日期" name="date" id="datepicker" value="${dayjs(new Date(), 'yyyy-MM-dd')}">
                                        </div>
                                    </div>
                                    <div class="row">
                                        <label class="col-sm-2 form-label">备注</label>
                                        <div class="col-sm-10">
                                            <textarea class="form-control" name="remark" rows="3"></textarea>
                                        </div>
                                    </div>
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                                    <button type="button" class="btn btn-dark">保存</button>
                                </div>
                            </form>
                        </div>
                    </div>
                `;
                new Litepicker({ element: document.getElementById('datepicker') });
                document.querySelector('#editor .btn-dark').addEventListener('click', () => {
                    const data = {};
                    new FormData(document.getElementById('editorForm')).forEach((v, k) => data[k] = v);
                    // if (item?.id) data.id = item.id; // 回款不能编辑，只能删除和新建

                    $.ajax({
                        url: `/customers/{{data.customer.id}}/contracts/${item.id}/receivables`,
                        type: 'post',
                        data,
                        statusCode: { 401: () => window.location.href = '/login', }
                    }).done(function () {
                        helper.toast('操作成功', 'success');
                    }).always(function () {
                        $('#editor').modal('hide');
                        app.loadContractList();
                    });
                });
                $('#editor').modal('show');
            });
        },
        openReceivableListModal(itemIndex) {
            const item = itemIndex > -1 ? app.data.contractList[itemIndex] : undefined;
            // show modal
            const modalEl = document.createElement('div');
            modalEl.id = 'modal';
            modalEl.className = 'modal fade';
            modalEl.setAttribute('aria-hidden', 'true');
            modalEl.setAttribute('tabindex', '-1');
            modalEl.setAttribute('data-bs-backdrop', 'static');
            modalEl.addEventListener('hidden.bs.modal', () => document.body.removeChild(modalEl));
            document.body.appendChild(modalEl);
            modalEl.innerHTML = `
                <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">回款信息</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                        </div>
                        <div class="modal-body">
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-dark" data-bs-dismiss="modal">关闭</button>
                        </div>
                    </div>
                </div>
            `;
            $('#modal').modal('show');
            app.loadReceivableList(itemIndex);
        },
        loadReceivableList(itemIndex) {
            const item = itemIndex > -1 ? app.data.contractList[itemIndex] : undefined;
            let rows = '';
            for (const r of item.receivables) {
                rows += `
                    <tr>
                        <td><div class="">${r.paymentMethod.name}</div></td>
                        <td>
                            <div class="d-flex align-items-center">
                                ¥${r.amount}
                            </div>
                        </td>
                        <td><div class="">${dayjs(r.date).format("YYYY-MM-DD")}</div></td>
                        <td><div class="">${r.remark}</div></td>
                        <td>
                            <div class="d-flex align-items-center">
                                ${item.isCompleted || item.isAbandoned ? '' : `<a class="text-danger ms-1" href="#" onclick="app.deleteReceivable(${itemIndex}, ${r.id})">删除</a>`}
                            </div>
                        </td>
                    </tr>
                `;
            }
            document.querySelector('#modal .modal-body').innerHTML = `
                <div class="table-responsive">
                    <table class="table table-bordered table-group-divider table-light">
                        <thead>
                            <tr>
                                <th scope="col">方式</th>
                                <th scope="col">金额</th>
                                <th scope="col">日期</th>
                                <th scope="col">备注</th>
                                <th scope="col">操作</th>
                            </tr>
                        </thead>
                        <tbody class="fs-sm">
                            ${rows}
                        </tbody>
                    </table>
                </div>
            `;

        },
        deleteReceivable(itemIndex, itemId) {
            const item = itemIndex > -1 ? app.data.contractList[itemIndex] : undefined;
            if (item && itemId) {
                helper.confirm('确定删除这条回款吗？', function () {
                    $.ajax({
                        type: 'delete',
                        url: `/customers/{{data.customer.id}}/contracts/${item.id}/receivables/${itemId}`,
                        statusCode: { 401: () => window.location.href = '/login', }
                    }).done(function () {
                        item.receivables = item.receivables.filter(v => v.id != itemId); // delete local
                        app.renderContractList(); // rerender contract list to refresh the progress bar
                        app.loadReceivableList(itemIndex);
                        helper.toast('操作成功', 'success');
                    });
                });
            }
        },
        // contract product
        openProductListModal() {
            // hide contract editor
            $('#contractEditor').hide();
            const usedSet = new Set();
            app.data.contractProductList.forEach(item => usedSet.add(item.productId));
            let productList = []; // cache
            const modalId = 'product-modal';
            const modalEl = document.createElement('div');
            modalEl.id = modalId;
            modalEl.className = 'modal fade';
            modalEl.setAttribute('aria-hidden', 'true');
            modalEl.setAttribute('tabindex', '-1');
            modalEl.setAttribute('data-bs-backdrop', 'static');
            modalEl.addEventListener('hidden.bs.modal', () => {
                document.body.removeChild(modalEl);
                $('#contractEditor').show(); // show contract editor again
            });
            document.body.appendChild(modalEl);
            modalEl.innerHTML = `
                <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">产品列表</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                        </div>
                        <div class="modal-body">
                            <div id="spinner" class="text-center" style="display: none;">
                                <div class="spinner-border" role="status"></div>
                            </div>
                            <div class="table-responsive"></div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                            <button type="button" class="btn btn-dark" data-bs-dismiss="modal">确定</button>
                        </div>
                    </div>
                </div>
            `;
            document.querySelector(`#${modalId} .btn-dark`).addEventListener('click', () => {
                try {
                    // 选择完成之后，将已经选择的产品写入到contractProductList中
                    app.data.contractProductList = [];
                    $(`#${modalId} table td .form-check-input`).each((i, el) => {
                        if (!!el.checked) {
                            app.data.contractProductList.push({
                                productId: productList[i].id,
                                name: productList[i].name,
                                unit: productList[i].unit,
                                sku: productList[i].sku,
                                purchase: productList[i].price,
                                price: productList[i].price,
                                quantity: 1,
                                discount: 0,
                            });
                        }
                    });
                    app.renderContractProductList(true);
                } finally {
                    $(`#${modalId}`).modal('hide');
                };
            });
            $(`#${modalId}`).modal('show');
            $(`#${modalId} spinner`).show();
            // load product list to choose
            $.ajax({
                type: 'get',
                url: '/products/search',
                data: { available: true },
            }).done(function (result) {
                productList = result.data || [];
                const table = document.querySelector(`#${modalId} .table-responsive`);
                let rows = '';
                const initSelectedCount = productList.filter(item => usedSet.has(item.id)).length || 0;
                for (let i = 0; i < productList.length; i++) {
                    const item = productList[i];
                    item._checked = usedSet.has(item.id);
                    rows += `
                    <tr id="row-${item.id}">
                        <td><input class="form-check-input m-0 align-middle" type="checkbox" ${item._checked ? 'checked' : ''}></td>
                        <td><div>${item.name}</div></td>
                        <td><div>${item.sku}</div></td>
                        <td><div>${item.unit}</div></td>
                        <td><div>${item.price}</div></td>
                    </tr>
                `;
                }
                const tableHTML = `
                    <table class="table table-bordered table-group-divider table-light">
                        <thead>
                            <tr>
                                <th scope="col">
                                    <input class="form-check-input m-0 align-middle" type="checkbox" ${initSelectedCount === productList.length ? 'checked' : ''}>
                                </th>
                                <th style="min-width:100px;">产品</th>
                                <th style="min-width:85px;">编号</th>
                                <th style="min-width:85px;">单位</th>
                                <th style="min-width:70px;">价格</th>
                            </tr>
                        </thead>
                        <tbody>
                            ${rows}
                        </tbody>
                    </table>
                `;
                table.innerHTML = tableHTML;
                $(`#${modalId} table th .form-check-input`)[0].indeterminate = initSelectedCount > 0 && initSelectedCount !== productList.length; // init
                $(`#${modalId} table td .form-check-input`).each((i, el) => {
                    el.addEventListener('change', () => {
                        productList[i]._checked = el.checked;
                        const isSemi = productList.findIndex(item => !!item._checked != el.checked) > -1;
                        const thCheckbox = $(`#${modalId} table th .form-check-input`).attr('semi', isSemi ? '1' : '0')[0];
                        thCheckbox.indeterminate = isSemi;
                        if (!isSemi) thCheckbox.checked = el.checked;
                    });
                });
                $(`#${modalId} table th .form-check-input`).click(function () {
                    let checked = this.checked;
                    if (this.getAttribute('semi') !== '0') checked = true;
                    this.checked = checked;
                    this.setAttribute('semi', '0');
                    productList.forEach(item => item._checked = checked);
                    $(`#${modalId} table td .form-check-input`).prop('checked', checked);
                });
            }).always(function () {
                $(`#${modalId} spinner`).hide();
            });
        },
        deleteContractProduct(index) {
            app.data.contractProductList = app.data.contractProductList.filter((_, i) => i !== index);
            app.renderContractProductList(true);
        },
        renderContractProductList(enableAction) {
            const contractEditorId = 'contractEditor';
            const table = document.querySelector(`#${contractEditorId} .table-responsive`);
            let rows = '';
            for (let i = 0; i < app.data.contractProductList?.length || 0; i++) {
                const item = app.data.contractProductList[i];
                rows += `
                    <tr id="contractProductRow-${i}">
                        <td>
                            <div>${item.name}</div>
                            <div class="fs-sm text-muted">${item.sku}</div>
                        </td>
                        <td>
                            <div>${enableAction ? `<input type="number" name="quantity" class="form-control form-control-sm input-short" min="0" value="${item.quantity}">` : item.quantity}</div>
                            <div class="fs-sm text-muted">单位:${item.unit}</div>
                        </td>
                        <td>
                            <div>
                                ${enableAction ? `<input type="number" name="purchase" class="form-control form-control-sm input-short" min="0" value="${item.purchase}">` : item.purchase}
                            </div>
                            <div class="fs-sm text-muted">原价:${item.price}</div>
                        </td>
                        <td>
                            <div>${enableAction ? `<input type="number" name="discount" class="form-control form-control-sm input-short" max="100" min="0" value="${item.discount}">` : item.discount}</div>
                        </td>
                        ${!!enableAction ? `
                            <td>
                                <a class="text-danger" href="#" onclick="app.deleteContractProduct(${i})">删除</a>
                            </td>
                        ` : ''}
                    </tr>
                `;
            }
            table.innerHTML = `
                <table id="contractProductTable" class="table table-bordered table-group-divider table-light">
                    <thead>
                        <tr>
                            <th style="min-width:100px;">产品</th>
                            <th style="min-width:85px;">数量</th>
                            <th style="min-width:85px;">价格</th>
                            <th style="min-width:70px;">折扣%</th>
                            ${enableAction ? '<th style="min-width:50px;">操作</th>' : ''}
                        </tr>
                    </thead>
                    <tbody class="fs-sm">
                        ${rows}
                    </tbody>
                </table>
            `;
            // add event
            const calculateContractAmount = () => {
                const contractAmountInput = $('#contractEditor #editorForm input[name="amount"]');
                const amount = app.data.contractProductList.reduce((acc, cur) => acc + (cur.purchase * cur.quantity), 0);
                contractAmountInput.val(amount);
            };
            $('#contractProductTable tbody tr').each((i, el) => {
                const item = app.data.contractProductList[i];
                const onInput = (event) => {
                    const who = event.srcElement.getAttribute('name');
                    const value = Number(event.srcElement.value);
                    switch (who) {
                        case 'quantity': {
                            item.quantity = value;
                            calculateContractAmount();
                            break;
                        }
                        case 'purchase': {
                            item.purchase = value;
                            calculateContractAmount();
                            break;
                        }
                        case 'discount': {
                            item.discount = Math.max(0, Math.min(100, value));
                            item.purchase = item.price * (100 - item.discount) / 100;
                            el.querySelector('input[name="purchase"]').value = item.purchase;
                            calculateContractAmount();
                            break;
                        }
                        default: break;
                    }
                };
                el.querySelectorAll('input').forEach(each => each.addEventListener('input', onInput));
            });
        },
        loadContractProductList(contract) {
            app.data.contractProductList = []; // clear old data
            if (!contract) return;
            $.getJSON(`/customers/{{data.customer.id}}/contracts/${contract.id}/products`).done(function (result) {
                app.data.contractProductList = result.data || [];
                app.renderContractProductList(!(contract && (contract.isAbandoned || contract.isCompleted)));
            });
        },
    };

    $(document).ready(async function () {
        app.switchTab('activity');
        app.tags.renderTags();
    });
</script>
{% endblock script %}